#pragma once

#include <iostream>
#include <string>
#include <functional>
#include <pthread.h>

template<class T>
using func_t = std::function<void(T&)>;

template<class T>
class Thread
{
public:
    Thread(const std::string& threadname, func_t<T> func, T& data)
    :_threadname(threadname), _func(func), _data(data), _isrunning(false), _tid(-1)
    {}
    static void* ThreadRoutine(void* arg)
    {
        Thread* ts = static_cast<Thread*>(arg);
        arg->_func(arg->_data);
        return nullptr;
    }
    bool Start()
    {
        int n = pthread_create(&_tid, NULL, ThreadRoutine, this);
        if(n == 0){//success
            _isrunning = true;
            return true;
        }else return false;
    }
    bool Join()
    {
        if(!_isrunning)return true;
        int n = pthread_join(_tid, NULL);
        if(n == 0)
        {
            _isrunning = false;
            return true;
        }
        return false;
    }
    std::string ThreadName()
    {
        return _threadname;
    }
    bool IsRunning()
    {
        return _isrunning;
    }
    ~Thread()
    {}

private::
    pthread_t _tid;
    func_t<T> _func;
    bool _isrunning;
    std::string _threadname;
    T _data;
};